/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DLSched;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalINIConfiguration;

/**
 *
 * @author G-spot
 */
public class DlSched implements Runnable
{

    private HierarchicalINIConfiguration config;

    public DlSched()
    {
        Logger.getLogger(DlSched.class.getName()).
                log(Level.INFO,
                    " ==== PROGRAM STARTUP ====");
        Handler handler = null;
        try
        {
            handler = new FileHandler("DlSched.log", 500000, 3, true);
            handler.setFormatter(new SimpleFormatter());
        }
        catch (IOException ex)
        {
            Logger.getLogger(DlSched.class.getName()).log(Level.SEVERE,
                                                          "IOException adding filehandler to logger", ex);
        }
        catch (SecurityException ex)
        {
            Logger.getLogger(DlSched.class.getName()).log(Level.SEVERE,
                                                          "SecurityException adding filehandler to logger", ex);
        }
        Logger.getLogger("").addHandler(handler);
    }

    /**
     * run
     * Starts new thread
     * The actual execution of the program. Will be the starting point of the
     * rest of the program.
     * 
     * Initiates a config object every time it is run.
     * 
     * @throws ConfigurationException 
     */
    @Override
    public void run()
    {
        try
        {
            config = new HierarchicalINIConfiguration("config.ini");
            config.setListDelimiter(',');

            Logger.getLogger(DlSched.class.getName()).
                    log(Level.INFO,
                        "Read config file");

            ArrayList<String> result_array = new ArrayList();
            
            for (Iterator plugins = config.getKeys("plugins");
                 plugins.hasNext();)
            {
                String plugin_name = plugins.next().toString();

                Logger.getLogger(DlSched.class.getName()).
                        log(Level.INFO,
                            "Checking plugin: {0}",
                            plugin_name);

                /* We are now going to download the file at the url given
                 * in the config file.
                 */

                String url_to_download = config.getString(plugin_name.substring(
                            plugin_name.indexOf(".") + 1) + ".url_to_download");
                String[] url_list = url_to_download.split(",");
                for (int i = 0; i < url_list.length; i++)
                {
                    Logger.getLogger(DlSched.class.getName()).
                        log(Level.INFO,
                            "url_to_download: {0}",
                            url_list[i]);
                    DLHtml.download_file(url_list[i]);

                    try
                    {
                        /* We are now going to get a class that is dynamically
                         * created from a string. The classname is gotten from
                         * the config file, in the format "plugins.classname",
                         * we therefore have to use a bit of substring magic to
                         * get only the classname
                         * NB!  It is important that the config plugin name be the
                         *      same as the actual classname
                         */
                        Logger.getLogger(DlSched.class.getName()).
                                log(Level.INFO,
                                    "Getting class: DLSched.Plugins.{0}",
                                    plugin_name.substring(
                                plugin_name.indexOf(".") + 1));

                        Class class_from_name = Class.forName("DLSched.Plugins."
                                                              + plugin_name.substring(
                                plugin_name.indexOf(".") + 1));

                        java.lang.reflect.Method obj_method = null;
                        try
                        {
                            obj_method = class_from_name.getMethod("get_links");
                            // get the constructor with one parameter
                            java.lang.reflect.Constructor constructor = null;
                            try
                            {
                                constructor = class_from_name.getConstructor();
                                // create an instance
                                Object invoker = null;
                                try
                                {
                                    invoker = constructor.newInstance();
                                    try
                                    {
                                        Object result =
                                               obj_method.invoke(invoker);       
                                        result_array.addAll((ArrayList<String>)result);
                                    }
                                    catch (IllegalAccessException ex)
                                    {
                                        Logger.getLogger(DlSched.class.getName()).
                                                log(Level.SEVERE, null, ex);
                                    }
                                    catch (IllegalArgumentException ex)
                                    {
                                        Logger.getLogger(DlSched.class.getName()).
                                                log(Level.SEVERE, null, ex);
                                    }
                                    catch (InvocationTargetException ex)
                                    {
                                        Logger.getLogger(DlSched.class.getName()).
                                                log(Level.SEVERE, null, ex);
                                    }
                                }
                                catch (InstantiationException ex)
                                {
                                    Logger.getLogger(DlSched.class.getName()).
                                            log(Level.SEVERE, null, ex);
                                }
                                catch (IllegalAccessException ex)
                                {
                                    Logger.getLogger(DlSched.class.getName()).
                                            log(Level.SEVERE, null, ex);
                                }
                                catch (IllegalArgumentException ex)
                                {
                                    Logger.getLogger(DlSched.class.getName()).
                                            log(Level.SEVERE, null, ex);
                                }
                                catch (InvocationTargetException ex)
                                {
                                    Logger.getLogger(DlSched.class.getName()).
                                            log(Level.SEVERE, null, ex);
                                }
                            }
                            catch (NoSuchMethodException ex)
                            {
                                Logger.getLogger(DlSched.class.getName()).
                                        log(Level.SEVERE, null, ex);
                            }
                            catch (SecurityException ex)
                            {
                                Logger.getLogger(DlSched.class.getName()).
                                        log(Level.SEVERE, null, ex);
                            }
                        }
                        catch (NoSuchMethodException ex)
                        {
                            Logger.getLogger(DlSched.class.getName()).
                                    log(Level.SEVERE, null, ex);
                        }
                        catch (SecurityException ex)
                        {
                            Logger.getLogger(DlSched.class.getName()).
                                    log(Level.SEVERE, null, ex);
                        }
                    }
                    catch (ClassNotFoundException ex)
                    {
                        Logger.getLogger(DlSched.class.getName()).log(Level.SEVERE,
                                                                      "Could not find class: "
                                                                      + plugin_name.substring(
                                plugin_name.indexOf(".") + 1), ex);
                    }
                }
            }
            Logger.getLogger(DlSched.class.getName()).
            log(Level.INFO, "Send links to file: {0}", result_array);
            WriteLink.write_links(result_array);
        }
        catch (ConfigurationException ex)
        {
            Logger.getLogger(DlSched.class.getName()).
                    log(Level.SEVERE,
                        "Exception creating new config object", ex);
        }

        /* This has the possible links now */
        /*ArrayList<String> usable_links = check_links(
        ParseHtml.get_links(
        config.getString("download.filepath")));*/

        Logger.getLogger(DlSched.class.getName()).
                log(Level.INFO,
                    "Run Complete");

        /*for (int i = 0; i < usable_links.size(); i++)
        System.out.println(usable_links.get(i));*/

    }

    public static void main(String[] args) throws ConfigurationException
    {
        HierarchicalINIConfiguration config =
                                     new HierarchicalINIConfiguration("config.ini");

        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        executor.scheduleAtFixedRate(new DlSched(), 0,
                                     config.getLong("general.interval"), TimeUnit.MILLISECONDS);
    }
}
